[TOC]
# innodb锁的模式
![](https://img.kancloud.cn/2c/df/2cdf7cab6418a8364cebeeef18e10a9a_835x280.png)
## 悲观锁(多写情况)
#### 1.是什么?
> 每次处理数据时, 都认为别人也会修改, 所以每次处理数据时, 先提前加锁, 再处理;
## 乐观锁(多读情况)
####  1.是什么?
> 每次处理数据时, 都认为别人不会修改, 所以每次处理数据时,
都不加锁, 只是在更新数据时, 判断下别人有没有在此期间修改过数据;
####  2.两种实现方式
####   2.1 \. 版本号机制
> 一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
####   2.2 \. CAS算法
> 即**compare and swap(比较与交换)**,是一种有名的**无锁算法**。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。
## 共享锁(读锁 s)
> 多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改
> 加锁: select \* from tb\_student where id = 1 **lock in share mode**
释放: commit / rollback
## 排他锁 (写锁 x):
> 排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
> InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型
> 加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select ...from...查询数据,因为普通查询没有任何锁机制
> select \* from tb\_student where id = 1 ** for update**
### 表锁
> 加表锁: lock table \[tableName\] \[read | write\]
> 释放表锁: unlock table
###意向锁
表锁和行锁存在冲突,比如:
1. transactionA获取了tableA中某一行的共享锁,其它事务就不能再修改这行数据了
2. trsactionB如果获取了tableA的表级排它锁,就可以对tableA的所有数据修改
这里 transactionB的表锁和transactionA的行锁就是冲突的
意向锁就是为了解决行锁和表锁的冲突,意向锁本身也是表级别的锁,事务在获取行锁前,必须先获取相应的意向锁,意向锁相当于一个标记,用来显示当前是否有事务锁住了表中的某一行
事务在获取表中某一行的 共享锁 前必须先获取到 意向共享锁或者更高级别的锁
事务在获取表中某一行的 排它锁 前必须先获取到 意向排它锁
#### 意向共享锁(Is):
#### 意向排他锁 (IX):
![](https://img.kancloud.cn/34/d2/34d23f2b28705b8dce9546081bd584cd_882x556.png)
### 记录锁(Record Lock)
select \* from \[tb\_name\] where id = #{id} for update
id列上有唯一索引,并且查询条件可以唯一确定一条记录,这时候innodb使用记录锁,只会锁住查出来的这一行记录
### 间隙锁(Gap Lock):
> where后面的字段有索引,但不是唯一索引,或者使用了>, < 等范围的查询条件时,查询条件范围内的索引值之间的间隙会被加锁,结果就是被加锁的间隙之间不能插入索引值
> 区间是左开右闭的
> 在InnoDB下,间隙锁的产生需要满足三个条件:
* 隔离级别为RR
* 当前读
* 查询条件能够走到索引
### 锁(Next-key Lock)
是行锁与间隙锁的组合
# 死锁
### 什么是死锁?
> 当两个事务都需要获得对方持有的排他锁才能完成事务,这样就导致了循环锁等待,也就是常见的死锁类型
### 产生的原因?
> Mysql行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,那么Mysql就会锁定这个主键索引,如果sql语句操作的是非主键索引,那么Mysql会先锁定这个非主键索引,再去锁定主键索引。
> 在UPDATE 和 DELETE操作时Mysql不仅会锁定所有WHERE 条件扫描过得索引,还会锁定相邻的键值。
### 解决死锁的方法?
> 1、 数据库参数
> 2、 应用中尽量约定程序读取表的顺序一样
> 3、 应用中处理一个表时,尽量对处理的顺序排序
> 4、 调整事务隔离级别(避免两个事务同时操作一行不存在的数据,容易发生死锁)
### 死锁的案例
> Test:(ID,STATE,TIME) 主键索引:ID 非主键索引:STATE
> 当执行"UPDATE STATE =1011 WHERE STATE=1000" 语句的时候会锁定STATE索引,由于STATE 是非主键索引,所以Mysql还会去请求锁定ID索引
> 当另一个SQL语句与语句1几乎同时执行时:“UPDATE STATE=1010 WHERE ID=1” 对于语句2 Mysql会先锁定ID索引,由于语句2操作了STATE字段,所以Mysql还会请求锁定STATE索引。这时。彼此锁定着对方需要的索引,又都在等待对方释放锁定。所以出现了"死锁"的情况。
# MVCC
* ## 是什么?
> `MVCC (Multiversion Concurrency Control)` 中文全称叫多版本并发控制,是现代数据库(包括 `MySQL`、`Oracle`、`PostgreSQL` 等)引擎实现中常用的处理读写冲突的手段,目的在于提高数据库高并发场景下的吞吐性能。
* ## 实现流程?
####   1.update修改的实现流程
> 1. 通过主键(或隐藏主键 DB_ROW_ID), 对该行加排他锁
> 2. 将这条记录, 原封不到的放入`undo log` 中, 记做nudolog1;
> 3. 执行修改, 会产生新的 事务, 所以在`undo log` 中产生新的一条记录,记做undolog2, 相比较undolog1, undolog2中会修改两个值;
> 3.1 修改第一个值: 事务ID(DATA_TRX_ID), 将其改成新的事务ID(例如 原本nudolog1中该值是1 , 那么undolog2中改成2);
> 3.2 修改第二个值: 指向回滚段指针(DATA_ROLL_PRE), 将其值指向undolog1;
> 如果对该行记录执行连续的update操作, 则重复上面2,3操作, 然后`undo log` 会形成链表, 遍历这个链表可以看到这条记录的变迁;
> 4. 记录 `redo log`,包括 `undo log` 中的修改
####   2.delete修改的实现流程
####   3.insert修改的实现流程
* ## 如何实现一致性读?
> 1.RU隔离级别下
> 直接读版本的最新记录就可以
> 2.RC 和 RR隔离级别下 (MVCC运行在这两个级别下)
> 在 `SELECT` 数据时就会用到版本链, 但是要读哪个版本下的记录就要决定于 , `ReadView`(可读视图)了
> 3.S隔离级别下
> 是通过加锁互斥来访问数据的, 用不到MVCC
*
# 相关命令操作
- 简介
- html
- js
- 正则表达式
- php
- 开发环境和配置
- PHP基础
- 变量
- 数据类型
- 函数
- 常量
- 运算符
- 流程控制
- 文件
- 异常处理
- 高级
- 会话控制
- 面向对象
- 框架
- laravel
- ThinkPhp
- Yii 易
- Yaf 亚夫
- Swooole
- python
- 数据库
- 基础
- 索引
- 倒排索引
- 关联sql
- 事务
- 锁
- 优化
- 安全性
- 数据库类型
- linux
- 基础命令
- shell脚本
- 操作系统和网络
- 版本控制器
- git
- git 命令行
- 小乌龟git的使用
- git 基础命令
- svn
- svn 命令行
- 小乌龟svn的使用
- 网络
- OSI七层模型
- 网络协议
- https协议
- TCP UTP协议
- 数据结构和算法
- 算法
- 时间复杂度
- 空间复杂度
- 排序算法
- 查找算法
- 数据结构
- 系统设计和架构
- 缓存系统
- redis
- lua
- memcached
- redis与memcached的区别
- 消息队列
- kafka
- 设计模式
- 单例模式
- 高并发和大流量设计
- 流量优化
- 前端优化
- web防盗链
- CDN加速
- 独立的图片服务器
- 服务器端
- 动态语言静态化
- 并发处理
- 数据库优化
- web服务器负载均衡
- 面试
- 项目整理
- novonordisk.micego.com
- nnm.micego.com
- www.dawang.tv
- lottery.3lotto.cn
- www.gpquan.cn
- in-tao.com
- 简历
- 面试问题
- 知识点
- 真题