MySQL锁分类
- 按性能分(抽象性,不真实存在这个锁)
1、乐观锁(比如使用version字段比对,无需等待)
2、悲观锁(需要等待其他事物) - 按访问模式分
1、读锁(共享锁)、写锁(排它锁)均为悲观锁 - 按粒度分
1、行级锁、页级锁、表级锁
InnoDB与MyISAM
Mysql 在5.5之前默认使用 MyISAM 存储引擎,之后使用 InnoDB 。查看当前存储引擎:
show variables like '%storage_engine%';
MyISAM 操作数据都是使用的表锁,你更新一条记录就要锁整个表,导致性能较低,并发不高。当然同时它也不会存在死锁问题。
而 InnoDB 与 MyISAM 的最大不同有两点:一是 InnoDB 支持事务;二是 InnoDB 采用了行级锁。也就是你需要修改哪行,就可以只锁定哪行。
在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。
排它锁
排它锁又称为写锁((eXclusive lock,简记为X锁)),若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。在更新操作(INSERT、UPDATE 或 DELETE)过程中始终应用排它锁。
共享锁
共享锁又称为读锁(Share lock,简记为S锁),若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。
- 数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。
1、单纯的查询(一致性非锁定读),mysql不会加锁,会用mvcc的机制读取数据。 - 排它锁和共享锁的兼容性
1.读写互斥
2.写写互斥
3.读读兼容 - 加锁语句
1.排它锁:SELECT * FROM table_name WHERE ... FOR UPDATE
2.共享锁:SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
- 读写锁参考文章
问题1:如果隔离级别为read uncommitted,并且有读写锁的话,是不可能出现脏读的。
问题1解决:sqlserver官网:在READ UNCOMMITTED级别运行的事务不会发出共享锁,以防止其他事务修改当前事务读取的数据。读取UNCOMMITTED事务也不被排他锁阻止,这将阻止当前事务读取已被修改但未被其他事务提交的行。设置此选项时,可以读取未提交的修改,称为脏读。可以更改数据中的值,并且行可以在事务结束之前在数据集中显示或消失。此选项与在事务中的所有SELECT语句中的所有表上设置NOLOCK具有相同的效果。这是隔离级别的最小限制。
问题1结论:读取UNCOMMITTED事务也不被排他锁(排他锁将阻止当前事务读取已被修改但未被其他事务提交的行)阻止。
所以最终结论是:read uncommitted 读不加锁,写加排他锁,并到事务结束之后释放。
间隙锁(Gap锁)
- 在范围查询的时候会出现间隙锁
- 防止幻读
1、符合条件的索引上都加X锁,对应的聚簇索引的主键也加上X锁,此外二级索引符合条件的记录前后间隙会加Gap锁,防止幻读 - 请求给一个不存在的记录加锁,Innodb也会使用间隙锁
1、查询/更新/新增一条不存在的记录
意向锁
未完待更新!
死锁
1、死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。
2、当事务试图以不同的顺序锁定资源时,就可能产生死锁。多个事务同时锁定同一个资源时也可能会产生死锁。
3、锁的行为和顺序和存储引擎相关。以同样的顺序执行语句,有些存储引擎会产生死锁有些不会——死锁有双重原因:真正的数据冲突;存储引擎的实现方式。
- 未完待更新!
行级锁
- 特点
1、比如修改一条数据的时候通过锁索引从非主键索引到主键索引来锁住这行数据,其他事务操作这条数据的事务阻塞,直到事务提交后释放 - 未完待更新!
表级锁
- 特点
1、比如修改一条数据且表中没有索引,它会锁住整个表,其他要操作本表的事务阻塞,直到事务提交后释放 - 不建议
1、表级锁它查找表中的所有数据,进行一个事务的操作效率极低 - 触发过程
1、比如表中没有索引,Innodb会触发表内隐藏的聚簇索引产生表锁 - 未完待更新!
加锁的过程
- 比如修改一条数据
1、server跟Innodb交互
2、Innodb根据server的条件,查询到这条数据加锁并一起返回给server
3、server修改完,直到事务提交才会释放锁
每个索引类型上可加的锁
https://blog.csdn.net/winterfeng123/article/details/79048524
https://www.jianshu.com/p/23524cc57ca4