[TOC]
### 读写锁(S-latch|X-latch)
innodb为了提高读的性能,自定义了read write lock,也就是读写锁。其设计原则是:
1、同一时刻允许多个线程同时读取内存中的变量
2、同一时刻只允许一个线程更改内存中的变量
3、同一时刻当有线程在读取变量时不允许任何线程写存在
4、同一时刻当有线程在更改变量时不允许任何线程读,也不允许出自己以外的线程写(线程内可以递归占有锁)。
5、当有rw\_lock处于线程读模式下是有线程写等待,这时候如果再有其他线程读请求锁的时,这个读请求将处于等待前面写完成。
从上面5点我们可以看出,rw\_lock在被占用是会处于读状态和写状态,我们称之为S-latch(读共享)和X-latch(写独占),《MySQL技术内幕:innodb引擎》对S-latch和X\_latch的描述如下:
| | S-latch | X-latch |
| --- | --- | --- |
| S-latch | 兼容 | 不兼容 |
| X-latch | 兼容 | 不兼容 |
innodb中的rw\_lock是在建立在自定义mutex\_t之上的,所有的控制是基于mutex和thread\_cell的。
在rw\_lock\_t获得锁和释放锁的主要接口是:rw\_lock\_s\_lock\_func、rw\_lock\_x\_lock\_func、rw\_lock\_s\_unlock\_func、rw\_lock\_x\_unlock\_func四个关键函数。 其中rw\_lock\_s\_lock\_func和rw\_lock\_x\_lock\_func中定义了自旋函数,这两个自旋函数的流程和mutex\_t中的自旋函数实现流程是相似的,其目的是要在自旋期间就完成锁的获得。
### 自旋锁
自旋锁的机制就是在短时间内循环获取锁,避免进程从用户态切换到内核态,因为上下文切换影响性能。超过一定时间后,进程仍然切换到阻塞状态,避免大量进程一直循环消耗CPU。
### 死锁与死锁检测
什么是死锁,通过以下的例子我们可以做个简单的描述:
线程A 线程B
mutex1 enter mutex2 enter
mutex2 enter mutex1 enter
执行任务 执行任务
mutex2 release mutex1 release
mutex1 release mutex2 release
上面两个线程同时运行的时候,可能产生死锁的情况,就是A线程获得了mutex1正在等待mutex2的锁,同时线程2获得了mutex2正在等待mutex1的锁。在这种情况下,线程1在等线程2,线程2在等线程就造成了死锁。
了解了死锁的概念后,我们就可以开始分析innodb中关于死锁检测的流程细节,innodb的检车死锁的实质就是判断
要进行锁的latch是否会产生所有线程的闭环,这个是通过sync\_array\_cell\_t的内容来判断的。在开始等待cell信号的时候,
会判断将自己的状态信息放入sync\_array\_cell\_t当中,在进入os event wait之前会调用sync\_array\_detect\_deadlock来判
断是否死锁,如果死锁,会触发一个异常。死锁检测的关键在与sync\_array\_detect\_deadlock函数。
以下是检测死锁的流程描述:
1、将进入等待的latch对应的cell作为参数传入到sync\_array\_detect\_deadlock当中,其中start的参数和依赖的cell参
数填写的都是这个cell自己。
2、进入sync\_array\_detect\_deadlock先判断依赖的cell是否正在等待latch,如果没有,表示没有死锁,直接返回.
如果有,先判断等待的锁被哪个线程占用,并获得占用线程的id,通过占用线程的id和全局的sync\_array\_t 等待cell数组状
态信息调用sync\_array\_deadlock\_step来判断等待线程的锁依赖。
3、进入sync\_array\_deadlock\_step先找到占用线程的对应cell,如果cell和最初的需要event wait的cell是同一
个cell,表示是一个闭环,将产生死锁。如果没有,继续将查询到的cell作为参数递归调用
sync\_array\_detect\_deadlock执行第2步。这是个两函数交叉递归判断的过程。
在检测死锁过程latch句柄、thread id、cell句柄三者之间环环相扣和递归,通过latch的本身的状态来判断闭环死锁。在上面的第2步会根据latch是mutex和rw\_lock的区别做区分判断,这是由于mutex和rw\_lock的运作机制不同造成的。因为关系数据库的latch使用非常频繁和复杂,检查死锁对于锁的调试是非常有效的,尤其是配合thread\_levels状态信息输出来做调试,对死锁排查是非常有意义的。
死锁示意图:

- CentOS运维手册
- CentOS6.9挂载额外的磁盘
- ACL(access control list)-权限控制
- 普通用户不能绑定80端口
- ssh8.1p1编译步骤
- 制作openssh8_1的rpm包
- 离线yum源维护
- 去除VIM中打开文件里有的^M字符
- Mysql运维手册
- CentOS6.9搭建Mariadb-Galera集群
- mysql编码报错
- haproxy代理mysql galera
- 常用sql
- MySQL通用知识点
- 修复断电损坏的MySQL数据表
- sync_binlog配置的分析
- Xtrabackup备份与恢复
- Innodb线程并发同步机制
- redo log
- 死锁分析
- 慢SQL分析
- nginx运维手册
- nginx日志分割
- proxy_set_header作用
- nginx优化
- url末尾不加/
- 负载均衡
- haproxy和nginx研究
- haproxy配置
- redis运维手册
- redis_5.0.8集群搭建
- Redis集群原理分析
- predixy的安装和配置
- redis优化
- NFS运维手册
- flock操作失败
- mongodb运维手册
- MongoDB开启用户认证
- shell编码规范
- HTTP
- HTTP的传输编码
- 性能分析
- java内存分析
- javaCPU分析