第37问:自旋锁 旋着旋着人就糊涂了

闭包星云
• 阅读 2744

第37问:自旋锁 旋着旋着人就糊涂了

问题

追求 MySQL 的性能时,总听说要调整自旋锁的参数: innodb_spin_wait_delay 和 innodb_sync_spin_loops,是真的么?

实验

首先我们要知道自旋锁的优点:自旋锁要上锁时,如果需要等待其他线程释放锁,那么:

  • 在等待锁的过程中会先线程会先自旋一段时间

    • 自旋阶段,线程不会放弃 CPU
  • 自旋过后:

    • 如果可以获取锁了,那么响应会比较快(自旋没发生上下文切换)
    • 如果还需要等待锁,再用更高成本的方式进行锁等待

innodb_spin_wait_delay 参数决定了自旋阶段的长度。现在我们试着调整 innodb_spin_wait_delay 参数,来测试一下:

先宽油起一个数据库,此处忽略步骤

建个表,放点数据:

第37问:自旋锁 旋着旋着人就糊涂了

配置好 performance_schema:

第37问:自旋锁 旋着旋着人就糊涂了

检查一下相关参数:

第37问:自旋锁 旋着旋着人就糊涂了

清理 performance_schema 的统计值:

第37问:自旋锁 旋着旋着人就糊涂了

来点压力:

第37问:自旋锁 旋着旋着人就糊涂了

查询一下锁等待成本最高的锁:

第37问:自旋锁 旋着旋着人就糊涂了

可以看到锁等待成本最高的是 lock_mutex,是保护 MySQL 锁系统的锁

下面我们来调整一下 innodb_spin_wait_delay,让自旋的时间变长:

第37问:自旋锁 旋着旋着人就糊涂了

重做一次压力(记得先清理统计数据),查看统计数据:

第37问:自旋锁 旋着旋着人就糊涂了

可以看到 lock_mutex 的平均等待时间从 751267 增加到了 1399041。我们让自旋阶段增加了 10 倍,锁等待的时间也会随之增大。

目前的实验看上去自旋阶段越短越好,那么自旋阶段是不是就没有意义了?当然不会。

大家可以将 innodb_spin_wait_delay 设置为 1,再进行测试,随着自旋阶段的减少,锁等待的时间也会随之增大(大部分锁都使用了高成本的方式来进行等待)。

那么如何选择自旋的参数呢?我们建议“不出问题不瞎调”。

在之前的统计数据中,时间的单位是:cycle,根据以下换算表,锁的平均时间是 1399041 cycle,大概也就 0.5ms(1399041 / 2385353233 = 0.00058 s),占 SQL 的整体时间很低,可以不用瞎调。

第37问:自旋锁 旋着旋着人就糊涂了

一个著名的 CPU 问题

自旋阶段,MySQL 会调用 CPU 的 PAUSE 指令,既能占用了 CPU,同时 PAUSE 指令(比起其他占用 CPU 的指令)也比较节能。

不过既然占用了 CPU,那么就会体现在 CPU 的使用率上。

现在我们将 innodb_spin_wait_delay 再放大一点比较一下:

第37问:自旋锁 旋着旋着人就糊涂了

可以看到 CPU 使用率会随着自旋阶段变长而升高

Intel 的 Skylake 系列 CPU,调大了 PAUSE 指令的周期时长。从 10 cycles 调大到 140 cycles(也许是因为让 PAUSE 周期变长更有利于节能)

类似于今天的实验,这个指令的调整相当于拉长了自旋阶段。

这就导致了在 Skylake 系列 CPU 下,MySQL 的锁表现和 CPU 占用率表现都有可能更糟糕。

(推荐文章:https://tech.meituan.com/2020...

小贴士

看到这里大家是不是开始焦虑了,要准备换 CPU 了?

其实不必焦虑,绝大部分情况下,大家不用追求极致的性能。比起榨取服务器的一点点极限性能,业务稍微调整一下 SQL 取得的收益会 大几个数量级。

俗话说:业务写得好,运维回家早。


关于 MySQL 的技术内容,你们还有什么想知道的吗?赶紧留言告诉小编吧!

第37问:自旋锁 旋着旋着人就糊涂了

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
java 里面 的锁
A、乐观锁、悲观锁B、偏向锁、轻量级锁、重量级锁C、互斥锁、自旋锁、适应性自旋D、可重入锁、读写锁E、公平锁、非公平锁F、总线锁、缓存锁(linux操作系统底层,由CPU提供的锁)G、锁优化:减少锁持有时间、减小锁粒度、锁分离、锁粗化、锁消除信号量与互斥量:信号
Wesley13 Wesley13
4年前
java 面试知识点笔记(十一)多线程与并发
自适应自旋锁:(java6引入,jvm对锁的预测会越来越精准,jvm也会越来越聪明)1.自选次数不再固定2.由前一次在同一个锁上的自旋时间及锁拥有者的状态来决定(如果在同一个锁对象上自旋等待刚刚成功获取过锁并且持有锁的线程正在运行中,jvm会认为该锁自旋获取到锁的可能性很大,会自动增加等待时间,相反jvm如果可能性很小会省掉自旋过程,
Wesley13 Wesley13
4年前
java中的锁
记录一下公平锁,非公平锁,可重入锁(递归锁),读写锁,自旋锁的概念,以及一些和锁有关的java类。公平锁与非公平锁:公平锁就是在多线程环境下,每个线程在获取锁时,先查看这个锁维护的队列,如果队列为空或者自身就是等待队列的第一个,就占有锁。否则就加入到等待队列中,按照FIFO的顺序依次占有锁。非公平锁会一上来就试图占
Wesley13 Wesley13
4年前
java面试题汇总,不断更新中。。。
JVM,并发,锁相关:1.请你谈谈对volatile的理解,volatile是否存在伪共享问题。2.cas你知道吗?3.原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗?4.公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁。5.CountDownLatch、CyclicBarrier、S
Easter79 Easter79
4年前
synchronized在jdk1.6之后引入的一些优化方案
自旋锁    jdk1.6之后默认开启,可以使用参数XX:UseSpinning控制,自旋等待不能代替阻塞,且先不说对处理器数量的要求,自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的,因此,如果锁被占用的时间很短,自旋等待的效果就会非常好,反之,如果锁被占用的时候很长,那么自旋的线程只会白白消耗处理器资源,而不会做任何有用的工
Wesley13 Wesley13
4年前
Java并发编程:AQS对CLH锁的优化
自旋锁适用于锁占用时间短,即锁保护临界区很小的情景<AQS的自旋锁详解(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzU3OTc1MDM1Mg%3D%3D%26mid%3D2247495307%26idx%3D1%26sn
Wesley13 Wesley13
4年前
Mysql 乐观锁 和悲观锁
平时看博客或技术文章的时候,经常被各种锁搞得晕晕乎乎,包括在自旋锁、可重入锁、公平锁等等、乐观锁、悲观锁、行锁、表锁、意向锁、排它锁等。前段时间终于把Java多线程相关的锁有机会学习了一遍。现在开始整理mysql相关的锁概念。先从乐观锁和悲观锁开始聊聊。首先要知道,乐观锁和悲观锁不是真实存在的锁,只是两种抽象概念性的东西,就相当于Java中的接口,只
Wesley13 Wesley13
4年前
JDK里的自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时才能进入临界区。JDK里面自旋锁的实现有SynchronousQueue 和LinkedTransferQueue。 本文只是自己对源码的简单理解。先说公平锁,先等待的线程先获得数据。SynchronousQueue的内部类TransferQueue实现了公平锁。
Stella981 Stella981
4年前
JVM中锁优化简介
本文将简单介绍HotSpot虚拟机中用到的锁优化技术。自旋锁互斥同步对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些操作给系统的并发性能带来了很大的压力。而在很多应用上,共享数据的锁定状态只会持续很短的一段时间。若实体机上有多个处理器,能让两个以上的线程同时并行执行,我们就可以让后面请求锁的那个线程原地自旋(
闭包星云
闭包星云
Lv1
我会一直陪着他,见证世间繁芜。
文章
3
粉丝
0
获赞
0