1. 什么是 rw-lock?

关于 rw-lock 官方文档中给出了如下说明:

rw-lock

The low-level object that InnoDB uses to represent and enforce shared-access locks to internal in-memory data structures following certain rules. Contrast with mutexes, which InnoDB uses to represent and enforce exclusive access to internal in-memory data structures. Mutexes and rw-locks are known collectively as latches.

rw-lock types include s-locks (shared locks), x-locks (exclusive locks), and sx-locks (shared-exclusive locks).

  • An s-lock provides read access to a common resource. ##共享 rw-lock 提供对资源的共享访问,允许对同一个资源加多个共享锁

  • An x-lock provides write access to a common resource while not permitting inconsistent reads by other threads.##独占 rw-lock 提供对该资源的独占访问,其他类型的rw-lock都和独占类型互斥

  • An sx-lock provides write access to a common resource while permitting inconsistent reads by other threads. sx-locks were introduced in MySQL 5.7 to optimize concurrency and improve scalability for read-write workloads. ##共享独占 rw-lock,提供对该资源的写访问,同时允许其他线程对该资源的非一致性访问。sx-lock 类型的 rw-lock 是 5.7 中引入用来提高 read-write 业务场景下的并发性能和可扩展性

The following matrix summarizes rw-lock type compatibility.

  S SX X
S Compatible Compatible Conflict
SX Compatible Conflict Conflict
X Conflict Conflict Conflict

See Also latch, lock, mutex, Performance Schema.

##简单的说 mutex 和 rw-lock 都是 innodb db 用来控制对内部内存数据结构的访问。mutex 用于资源的互斥访问,rw-lock 用于资源的共享访问(共享访问,说白了就是为了提高并发性能)。rw-lock 用于控制公共共享资源的访问,例如 buffer_pool pages,tablespaces,adaptive search systems,data-dictionary,information_schema等。

##简而言之,rw-lock 在innodb系统中起着非常重要的作用,所以了解如何跟踪和监控并读懂监控数据对我们来说就很重要了。

2.如何监控 rw-lock

我们使用 show engine innodb status\G; 就可以收集到 rw-lock 的信息。在输出信息中 SEMAPHORES 部分的结尾会给出 rw-lock 的统计信息。如下:

----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 4838871
--Thread 139807778121472 has waited at row0ins.cc line 2885 for 0 seconds the semaphore:
X-lock on RW-latch at 0x7f2a92631e08 created in file buf0buf.cc line 781
a writer (thread id 139828041455360) has reserved it in mode  exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file lob0first.h line 151
Last time write locked in file /export/home/pb2/build/sb_0-37170812-1575922551.75/rpm/BUILD/mysql-8.0.19/mysql-8.0.19/storage/innobase/row/row0ins.cc line 2885--Thread 139828041455360 has waited at buf0buf.cc line 2945 for 0 seconds the semaphore:
Mutex at 0x7f31b0341bc0, Mutex BUF_POOL_LRU_LIST created buf0buf.cc:1228, lock var 1--Thread 139806828852992 has waited at buf0buf.cc line 4652 for 0 seconds the semaphore:
Mutex at 0x7f31b0341bc0, Mutex BUF_POOL_LRU_LIST created buf0buf.cc:1228, lock var 1
......
......
OS WAIT ARRAY INFO: signal count 33698998
RW-shared spins 13113391, rounds 13420662, OS waits 289926
RW-excl spins 6261445, rounds 19356721, OS waits 326460
RW-sx spins 842149, rounds 15553439, OS waits 343381
Spin rounds per wait: 1.02 RW-shared, 3.09 RW-excl, 18.47 RW-sx#该示例中因为当前系统中有 rw-lock 及 Mutex 锁等待,如果没有等待输出如下:----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 4838871
OS WAIT ARRAY INFO: signal count 33698998
RW-shared spins 13113391, rounds 13420662, OS waits 289926
RW-excl spins 6261445, rounds 19356721, OS waits 326460
RW-sx spins 842149, rounds 15553439, OS waits 343381
Spin rounds per wait: 1.02 RW-shared, 3.09 RW-excl, 18.47 RW-sx#reservation count 表示在sync array中分配 slot 的次数(这个次数等不等于进入OS wait 的次数我还不确定)
#signal count 表示进入 OS wait 的线程被唤醒的次数
#

3. rw-lock 统计信息的计算方式及各指标具体含义

NOTE: 重点来了,你看懂了 rw-lock 的计算方式,上面的那些指标你自然也就知道代表什么意义了

rw-lock 自旋算法

rw-lock 锁定步骤如下:Step-1:尝试获取所需要的 rw-lock#如果获取所成功,则过程结束返回。此时 rw-lock 相关统计信息为(spins=0, rounds=0, os-waits=0)#如果获取锁失败则进入 spin-loopStep-2:开始spin loop过程,并且spin-count计数加1
#这里第一步获取锁失败以后为什么是进入 spin-loop 而不是直接进入 os-wait?这是因为通常 rw-lock都是短期持有,所以spin后重新获取的概率很高,而进入os-wait会进行上下文切换是个很重的操作Step-3:进行 N 轮的 spining(N值由参数innodb_sync_spin_loops决定,默认值是30)
Step-3a:在每个循环过程中会调用 PAUSE logic(PAUSE 使cpu一定时间内处于暂停状态)
Step-3b:每个循环完成后会检查所需要的锁是否可用,如果可用则退出循环,进入下面的Step-c
#如果循环后检查锁并不可用,那么就继续spin-loop,这个没有什么疑问
Step-3c:再次尝试获取锁需要的锁如果获取锁成功,则过程结束。(spins=1, rounds=M (M <= N), os-waits=0)如果获取锁失败,并且N次的循环还没有用完,则继续进行spin-loop
#注意为什么线程检查rw-lock可用退出spin-loop去获取又失败呢?因为可能有多个线程都在等待该锁,所以该锁可能被其他线程先获取,在并发环境中这并不奇怪
Step-3d:如果线程进行了N次spin依然没有获得rw-lock,这时该线程会向 sync-array infrastructure 中注册自己的信息(以便在相关rw-lock可用时自己能够被唤醒),然后进入os-wait(这时os-waits计数会加1)
#注意在注册完自己的信息之后进入os-wait之前线程还会再次检查一次锁是否可用,因为注册信息是需要时间的,也许在这个过程中所已经可用了
Step-3e:如果线程被 sync-array infrastructure 唤醒,则尝试获取锁如果成功,则过程结束。(这时rw-lock统计信息为(spins=1, rounds=N, os-waits=1))如果失败,则跳到Step-3开始新一轮的 N(30) 次 spin操作(注意这时 rw-lock 的统计信息中spins计数并不会增加)

好了,解释了rw-lock 的加锁步骤,下面我们就可以来看一下 show engine innodb status\G;中输出的 rw-lock 统计信息的具体含义了

spins:代表有多少第一次获取 rw-lock 失败,并且进入 spin-loop(在上面获取锁的步骤中已经解释了由os-wait等待被唤醒,然后获取锁失败,再次进入spin-loop时 spins是不会增加的)

rounds:代表一共有多少次 PAUSE logic 被执行(因为没进行一次 spin 循环都会执行一次 PAUSE logic)

os-waits:代表一共进行了多少次完整的spin-loop依然未获得锁,而不得进入os-wait等待

3.示例

上面我们已经详细的解释了怎么读懂 rw-lock 的统计数据,下面我们来看一些示例

3.1 示例1

RW-shared spins 338969, rounds 20447615, OS waits 592941
RW-excl spins 50582, rounds 1502625, OS waits 56124
RW-sx spins 12583, rounds 360973, OS waits 10484
Spin rounds per wait: 60.32 RW-shared, 29.71 RW-excl, 28.69 RW-sx

#我们只看一下 RW-shared 指标,其他指标分析方法是一样的。spins 338969 表示一共发生了 338969 次第一次获取 RW-shared 失败(注意关键词第一次)。rounds 20447615 表示一共调用了20447615次 PAUSE logic,rounds/spins≈60 ,OS waits/spins≈1.75,表示平均每次获取 RW-shared 锁需要消耗60次PAUSE logic 加上 1.75次 OS waits

##从上面数据我们看到系统争用比较严重,同时当前设置的innodb_sync_spin_loops值并不足够使线程获取所需的锁。

3.2 示例2

RW-shared spins 35943, rounds 777178, OS waits 19051
RW-excl spins 4269, rounds 121796, OS waits 4164
RW-sx spins 13407, rounds 321954, OS waits 7346
Spin rounds per wait: 21.62 RW-shared, 28.53 RW-excl, 24.01 RW-sx

#spins 35943 表示一共发生了 35943 次第一次获取 RW-shared 失败(注意关键词第一次)。rounds 777178 表示一共调用了  777178 次 PAUSE logic,rounds/spins≈21 ,OS waits/spins≈0.5,表示平均每次获取 RW-shared 锁需要消耗 21 次PAUSE logic 加上 0.5次 OS waits

##从上面数据我们看到系统有一定的争用,但是并不是特别严重。

3.3 示例3

RW-shared spins 39578, rounds 424553, OS waits 7329
RW-excl spins 5828, rounds 78225, OS waits 1341
RW-sx spins 11666, rounds 67297, OS waits 449
Spin rounds per wait: 10.73 RW-shared, 13.42 RW-excl, 5.77 RW-sx

#spins 39578 表示一共发生了 39578 次第一次获取 RW-shared 失败(注意关键词第一次)。rounds 424553 表示一共调用了  424553 次 PAUSE logic,rounds/spins≈10 ,OS waits/spins≈0.18,表示平均每次获取 RW-shared 锁需要消耗 10 次PAUSE logic 加上 0.18 次 OS waits。

##从上面数据我们看到大概只有 7329(即大约不到20%) 次申请RW-shared锁发生了 OS wait(当然有可能更低,因为有可能某些获取发生了多次的OS wait)。平均获取锁需要 10次 PAUSE logic 和 0.18 次 OS wait,说明系统的争用比较低。

4.关于 rw-lock 争用优化

上面的第一个例子中争用特别严重,如果我们通过调整参数或者应用代码降低了 rounds/spins 和 waits/spins 就算有效调优吗?并不见得,我们还需要观察其他方面,比如说 TPS 是提高还是降低,QPS是提高了还是降低了等等。

因为 os wait 会有上下文切换是个比较重的操作,可能很多人觉得对于第一个列子应该增加 spin-loop (innodb_sync_spin_loops),看似没有问题,但是如果我们把 innodb_sync_spin_loops增加到某个值以上可能会浪费更多的cpu时间(如果实际获取锁的时间比较长,这时候会一直进行spin-loop操作,浪费更多的cpu时间,特别是如果最后还是进入了os wait)。

5. 影响 rw-lock 统计数据准确性的相关 bug

https://bugs.mysql.com/bug.php?id=99171

 

如何读懂 MySQL rw-lock 锁的统计信息相关推荐

  1. mysql 默认事务隔离级别_一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: <一文学会MySQL的explain工具> <一文读懂MySQL的索引结构及查询优化> (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论 ...

  2. 一篇文章读懂MySQL的各种联合查询

    一篇文章读懂MySQL的各种联合查询 联合查询是指将两个或两个以上的表的数据根据一定的条件合并在一起! 联合查询主要有以下几种方式: 全连接:将一张表的数据与另外一张表的数据彼此交叉联合查询出来 举例 ...

  3. 一文读懂 MySQL Explain 执行计划

    一.前言 上周老周的一个好朋友让我出一篇教你读懂 SQL 执行计划,和我另一位读者反馈的面试题如何排查慢 SQL 的强相关,索性先出一篇一文读懂 MySQL Explain 执行计划.Explain ...

  4. 读懂mysql慢查询日志

    我们来看一下如何去读懂这些慢查询日志. 在跟踪慢查询日志之前,首先你得保证最少发生过一次慢查询.如果你没有可以自己制造一个: root@server# mysql -e 'SELECT SLEEP(8 ...

  5. 学会读懂 MySql 的慢查询日志

    在前边的博客< 何时.如何开启 MySql 日志?>中,我们了解到了如何启用 MySql 的慢查询日志.今天我们来看一下如何去读懂这些慢查询日志. 在跟踪慢查询日志之前,首先你得保证最少发 ...

  6. 6.读懂mysql执行计划

    文章目录 1.执行计划概念和语法 1.执行计划的概念 2.执行计划的语法 1.常规执行计划语法 2.扩展执行计划的语法 3.分区表的执行计划语法 2.执行计划包含的信息 1.id​:查询的顺序 2.s ...

  7. 一文读懂MySQL查询语句的执行过程

    需要从数据库检索某些符合要求的数据,我们很容易写出 Select A B C FROM T WHERE ID = XX  这样的SQL,那么当我们向数据库发送这样一个请求时,数据库到底做了什么? 我们 ...

  8. 一文读懂MySQL事务锁、事务级别

    锁 性能分:乐观(比如使用version字段比对,无需等待).悲观(需要等待其他事务) 乐观锁,如它的名字那样,总是认为别人不会去修改,只有在提交更新的时候去检查数据的状态.通常是给数据增加一个字段来 ...

  9. 一篇文章带你读懂 MySQL 和 InnoDB

    作者 | Draveness  原文地址 | http://draveness.me/mysql-innodb.html 作为一名开发人员,在日常的工作中会难以避免地接触到数据库,无论是基于文件的 s ...

  10. 一文彻底读懂MySQL事务的四大隔离级别

    前言 之前分析一个死锁问题,发现自己对数据库隔离级别理解还不够深入,所以趁着这几天假期,整理一下MySQL事务的四大隔离级别相关知识,希望对大家有帮助~ 事务 什么是事务? 事务,由一个有限的数据库操 ...

最新文章

  1. 中医研究登上Nature
  2. 【转】python中的字符数字之间的转换函数
  3. LintCode 用递归打印数字
  4. lamp 独立mysql_lamp or lnmp 环境搭建之独立安装mysql数据库
  5. PHPExel导出报表--导出类
  6. 修改linux默认启动级别(包括Ubuntu)
  7. sun.misc.unsafe类的使用
  8. Mysql连接错误:Mysql Host is blocked because of many connection errors
  9. c语言 define宏名称if(参数),宏编程基础内容
  10. 南京农业大学 操作系统课程设计
  11. try catch 的使用
  12. L1-7 机工士姆斯塔迪奥【C语言】
  13. Laravel版本更新异常4.2.8- 4.2.9 Declaration of ... CompilerEngine ... should be compa
  14. (附源码)计算机毕业设计SSM家具商城系统
  15. 基于android的汽车租赁系统app
  16. 凛冬至,这一杯互联网咖啡能热多久?
  17. Elasticsearch 时间类型总结
  18. [论文阅读1]Re-identification with RGB-D sensors
  19. Marvell 交换芯片DSA(分布式交换架构)功能介绍
  20. OIM同步OID(OID-Connector 9.0.4.12)

热门文章

  1. 25年前,开发者如何将游戏塞进内存?
  2. 【matplotlib】plot()kind参数表
  3. oracle minus连接条件,oracle及sqlserve中MINUS 的使用方法
  4. 代写php代码作业,C++代写 CS 100 Project Two代做php实验作业
  5. 记录一个非常好用的模拟器:夜神模拟器
  6. java实例分析宠物商店_Java实现宠物商店管理
  7. 服装系统mysql设计_服装行业ERP系统的设计与实现-店铺模块(SSH,MySQL)(含录像)
  8. 用计算机语言写结婚祝福语,[结婚电子显示屏祝福语]电子显示屏结婚贺词
  9. 【转】完美:photoshop cs6 破解版下载[序列号+破解补丁+破解教程+官方原版]
  10. Android进阶-NDK学习完整版