mysql:悲观锁、乐观锁,表锁、行锁,共享锁、排他锁

锁的模式:乐观锁 、悲观锁

乐观锁

相当于乐观的人,总是想着事情往好的方向发展

乐观锁是指对数据库进行 增、删、改 操作时,想法很乐观,认为这次的操作不会导致冲突,在操作数据时,不进行加锁处理,而在进行更新后,再去判断是否有冲突

使用场景

适用于写比较少的情况下,多用于读

实现方式

数据库没有实现功能,需要开发者实现:

  • 版本号机制
    在数据表中加上一个数据版本号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


原文出处:/show_1IXqfxw9xpq.html