锁的模式:乐观锁 、悲观锁
乐观锁
相当于乐观的人,总是想着事情往好的方向发展
乐观锁是指对数据库进行 增、删、改 操作时,想法很乐观,认为这次的操作不会导致冲突,在操作数据时,不进行加锁处理,而在进行更新后,再去判断是否有冲突
使用场景
适用于写比较少的情况下,多用于读
实现方式
数据库没有实现功能,需要开发者实现:
版本号机制
在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。要update该条记录时,先读取该条记录,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。CAS算法实现
具体参见:https://blog.csdn.net/qq_34337272/article/details/81072874
悲观锁
悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过 获取锁 才能进行操作
与java中的synchronized类似,所以悲观锁需要耗费较多的时间。
应用场景
一般多写的场景下
实现方式
由数据库实现
锁的范围:表锁 、行锁
表锁
MyISAM 存储引擎不支持事务,使用 表锁,就是锁一整张表,更新一条记录就要锁整个表,导致性能较低,并发不高。
不会死锁
行锁
InnoDB 存储引擎支持事务,使用 行锁,在事务中,修改哪行,就只锁定哪行
行锁并不是直接锁记录,而是锁索引
索引分为 主键索引 和 非主键索引 两种:
如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;
如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引
如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。
也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。
锁的属性:共享锁、排他锁
共享锁
又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改,要想修改就必须等所有共享锁都释放完之后。
select 语句
select可以通过 select ... lock in share mode 加共享锁
排他锁
又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
delete、insert、update 语句
都会自动给涉及到的数据加上排他锁
select 语句
select语句默认不会加任何锁,所以可以查询被 排他锁 锁住的记录
select可以通过 select ...for update 加排他锁
操作参见:
https://www.cnblogs.com/edgedance/p/6979633.html