MySQL锁的分析实战MySQL锁的分类:MySQL行锁

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

MySQL锁的分类:

根据细粒度的去划分

1. 悲观锁和乐观锁

(1)悲观锁

悲观锁对于数据库的操作,持久悲观态度, 所有的数据处理的操作过程中,他会有将相应的数据锁定,以其他应用系统无法修改,当前要使用的数据。

修改数据,会加锁,但是会影响数据库的性能,随之而来的就是,响应速度的降低;

(2)乐观锁

数据操作过程中,对于数据处理的持有乐观态度,在整个数据处理过程中,一般由具体的数据版本号去处理和触发类似于version的版本号字段,可以使用到, 其中对于数据更新的时候,将提交数据的版本与今天的版本号

2.读写锁

通常是在于数据读取和,数据更新的时候用到的,

读锁,当前数据,一份数据可以加多个读锁而不互相影响,读锁具有共享性

写锁,同一份数据,一旦加写锁,则不能增加写锁和读锁

直至释放掉读写锁之后,就可以了


很多的具体操作,在运行的过程中,读锁是我们常用到的,用于读取数据之后,更新数据,

先读后写,可以避免 不可重复写操作,


表锁, 行锁,页面锁

表级锁,进行加锁和释放锁, 开销;

加锁--> 表共享锁,表独占锁

表锁-> 不能对表进行操作, 当一个线程获取一个表的写锁,只有持有锁的线程可以, 表进行更新操作其他线程对数据表的读写操作 都会堵塞,直到写锁被释放为止

MySQL行锁和表锁分析

其实主要的是针对于单条数据的记录的行锁 或者表锁;

表级锁模式:

  • 表共享锁
  • 独占写锁

线程获取表的读锁之后,其他线程仍然对表可以读操作,但是不能对表进行操作,

MySQL命令添加表锁

  1. 添加表级锁,读锁或者写锁
 lock table  表名称  read(write);


  lock table  data read ;添加读锁表级别的
  
  
  lock table  data write ;添加写锁表级别的
  
  
  删除 表锁命令
  
  unlock  tables;
复制代码

MySQL的行锁

行锁是针对于特点的数据记录,

对于当前MySQL的主流存储引擎,innoDB中,有两种类型的行锁,

  • 共享锁
  • 排他锁

其中 共享锁--->一个事务只能读取一行数据, 并且添加了共享锁之后的数据,就不能给增加排他锁;

排他锁--->对于当前事务,中的数据进行数据的CRUD的操作,并且当前的数据行,不能增加排他锁和共享锁

其中比较重要的是,对于主要的数据表中的索引字段,如果对非索引字段进行设置行锁,可能会将行锁编成表锁。

可以使用

lock in share mode 命令--->共享锁

select * from data where id =1 for update

区分行锁和表锁的关键,是看当前的锁,是针对对全部的数据表的,还是只是当前更新数据的记录的,

比如 当前我要下单一个商品,只是在当前记录表的数据增加或者修改,

这个就是行级数据,进行操作

如果是我对这个表操作, 比如高并发的环境下,对其当前表增加一个数据,但是 支持的并发比较低,相应的数据安全的性能也比较低,

牺牲性能来保证数据安全

MySQL死锁是如何产生的

能说是死锁是如何产生的吗?

好多面试的时候,都会遇到一个比较难得话题,死锁,既考虑业务的逻辑关系,也要考虑自己对于死锁理解的能力,

1.为什么会发生死锁

锁的好处,为了数据安全,但是会减少性能,降低并发虽然可以一定程度上解决并发的问题,但是依旧会发生死锁,导致锁未及时释放的从而,引发很大的问题,

2.死锁发生的条件(前提)

(1)互斥条件在当前时间中,计算机中的某个数据只能被一个线程所占用,其他线程要是访问,只能是等待

(2) 不可剥夺条件

某个线程获取的数据资源使用完成之前,不能由其他线程强行抢占(只能是当前线程自己释放)

(3)请求与保持条件

当前线程已经获取到一个资源,但是又想访问另一个资源, 但是请求的资源被其他线程正在调用,

举个例子:当前回到家,然后家想去上厕所,但是进入家里有一个大门,而且进入之后还要去厕所

进入大门--->获取厕所的锁--> (但是现在已经有人在厕所了)-->

只能等待,别人使用完厕所,再次使用这时候,当前的线程只能处于一个阻塞等待的状态;

(4)循环等待条件

当前系统中的各个线程是相互等待的,比如A线程要在使用B线程的资源,但是进程B请求进程C占用, 进程C请求的资源 进程A占用, 形成了循环等待条件

这个四个条件缺一不可,直至四个条件,都满足的时候,会发生死锁;

处理死锁的方式

  • 预防死锁
  • 避免死锁
  • 检测死锁
  • 解除死锁

一般情况下,我们要避免死锁,开始使用;

初识MVCC

死锁通常是对于资源占用之后,没有及时的释放,导致了资源一直被锁定的状态。

1.解除死锁的方法:

本质上是将当前的进程从死锁的状态解脱出来;

在实际工作用,主要是用于 银行家算法资源分配法这两种方式来避免死锁。

2.MySQL的死锁问题:

在Mysql,默认的存储引擎是InnoDB,其中这个引擎是会产生死锁的问题,这个是行锁级别的问题,

其中这个InnoDB存储引擎,---->等待图;

如果发生死锁,等待图会如何做呢?

在运行过程中,等待图的方式会检测死锁,如果发生死锁,就会自动的回滚一个事务。

一般是MySQL的中,可以这样做避免死锁?

  • 索引避免无效索引,导致行锁升级为表锁
  • 设计索引,尽量缩小锁的范围
  • 控制特定事务的大小,加锁操作在事务的最后执行,尤其是写操作;
  • 使用低级别的事务隔离机制

InnoDB中Mvcc原理

其中这个数据库中的MVCC的机制主要用于并发操作下的数据更新以及CRUD。

本质上是,MVCC机制是对于数据库中数据某个时间点的数据快照

也就是说,同一个读的操作,按照相同的条件查询数据,在当前情况下,查到的结果都是一样的,

但是从另外一个角度看,不同事务,在同样时间中,看到的数据表中的数据也可能是不同的。

MVCC的组成机制

Mvcc的机制是通过每行数据表记录后面两个具体的列(隐藏)来实现的;

其中一列会保存行的创建本号,另一个是保存行的过期版本号;

用于对于每次事务开始之前,和每行之前记录的版本号进行对比。

一般是新的事务,就会递增这个版本号