写点什么

MySQL 锁的分析实战

作者:卢卡多多
  • 2021 年 12 月 08 日
  • 本文字数:2264 字

    阅读完需:约 7 分钟

MySQL锁的分析实战

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 的机制是通过每行数据表记录后面两个具体的列(隐藏)来实现的;


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


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


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

发布于: 1 小时前阅读数: 9
用户头像

卢卡多多

关注

努力寻找生活答案的旅途者 2020.04.12 加入

公众号:卢卡多多,欢迎一起交流学习

评论

发布
暂无评论
MySQL锁的分析实战