mysql是怎么加锁的 24排量能跑多快( 二 )


意向锁,为了避免DML在执行时 , 加的行锁与表锁的冲突,在innodb中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查 。意向锁分为,意向共享锁is由语句select ... lock in share mode添加 。意向排他锁ix,由insert,update,delete,select 。。。for update 添加 。
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_lock;
行级锁 , 每次操作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最高,并发读最高,应用在innodb存储引擎中 。
innodb的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的 , 而不是对记录加的锁,对于行级锁,主要分为以下三类:
1、行锁或者叫record lock记录锁,锁定单个行记录的锁,防止其他事物对次行进行update和delete操作,在RC,RR隔离级别下都支持 。
2、间隙锁Gap lock,锁定索引记录间隙(不含该记录),确保索引记录间隙不变 , 防止其他事物在这个间隙进行insert操作 , 产生幻读,在RR隔离级别下都支持 。
3、临键锁Next-key-lock,行锁和间隙锁组合 , 同时锁住数据,并锁住数据前面的间隙Gap,在RR隔离级别下支持 。
innodb实现了以下两种类型的行锁
1、共享锁 S: 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁 。
2、排他锁 X: 允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁 。
insert 语句 排他锁 自动添加的
update语句 排他锁 自动添加
delete 语句 排他锁 自动添加
select 正常查询语句 不加锁。。。
select。。。lock in share mode 共享锁 需要手动在select 之后加lock in share mode
select。。。for update 排他锁 需要手动在select之后添加for update
默认情况下,innodb在repeatable read事务隔离级别运行 , innodb使用next-key锁进行搜索和索引扫描,以防止幻读 。
间隙锁唯一目的是防止其它事务插入间隙,间隙锁可以共存 , 一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用的间隙锁 。
详解MySQL(InnoDB)如何处理死锁 锁是需要事务结束后才释放的 。
一个是 MVCC,一个是两阶段锁协议 。
为什么要并发控制呢?是因为多个用户同时操作 MySQL 的时候 , 为了提高并发性能并且要求如同多个用户的请求过来之后如同串行执行的一样(为了解决脏读、不可重复读、幻读)
官方定义:
两阶段锁协议是指所有事务必须分两个阶段对数据加锁和解锁,在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁;在释放一个封锁之后,事务不再申请和获得任何其他封锁 。
对应到 MySQL 上分为两个阶段:
但是两阶段锁协议不要求事务必须一次将所有需要使用的数据加锁(innodb在需要的索引列数据才锁行),并且在加锁阶段没有顺序要求,所以这种并发控制方式会形成死锁 。
MySQL有两种死锁处理方式:
死锁检测 (默认开启)
死锁检测的原理是构建一个以事务为顶点、锁为边的有向图,判断有向图是否存在环,存在即有死锁 。
回滚
检测到死锁之后,选择插入更新或者删除的行数最少的事务回滚,基于 INFORMATION_SCHEMA.INNODB_TRX 表中的 trx_weight 字段来判断 。
收集死锁信息:
减少死锁:
死锁解决:
mysql读数据时怎么加写锁加锁情况与死锁原因分析
为方便大家复现 , 完整表结构和数据如下:

推荐阅读