java面试题-mysql中的 锁 你知道多少?

发布时间:2024年01月05日

?远离八股文,面试大白话,通俗且易懂

看完后试着用自己的话复述出来。有问题请指出,有需要帮助理解的或者遇到的真实面试题不知道怎么总结的也请评论中写出来,大家一起解决。

java面试题汇总-目录-持续更新中

?锁一直是我比较模糊的一块知识点,因为平时做的项目并发量并不是特别大。所以实际项目中很难有确切的体会。但是他又是面试中的高频问点,所以还是查阅资料以及结合项目后,整理了一份,争取彻底弄清楚!

下面这个图是我整理的一个大概的分类,并且会逐个介绍:

第一:mysql的两种引擎

首先,我们需要知道一下mysql中的两个引擎分别是:InnoDB、MyISAM

但是他俩的区别这篇文章就先不解释,不然会乱。

InnoDB引擎从mysql5.5之后就是mysql的默认引擎了。

我们需要知道的是:

InnoDB支持表级锁、行级锁

MyISAM支持表级锁,不支持行级锁

第二:乐观锁和悲观锁思想

从上图也可以看出,我在乐观锁和悲观锁后面都加了两个字--思想

是的,这两个锁其实就是我们遇到高并发时候的一种解决思想,他不代表具体的实现方式。

悲观锁:顾名思义就是我认为你只要来修改我的数据,我就认为别人也可能会来修改数据。不管有没有只要一开启事务就都加锁。直到处理完成之后,才允许别人修改。

????????-- 虽然安全级别较高,但是有利也有弊。弊端就是会影响整个流程的效率。所以他的使用场景是在数据修改频率较高的场景下,如果只是读取数据,你使用悲观锁就不太合适了。

?

乐观锁:和悲观锁相对的就是乐观锁。它的思想就是假设整个事务过程中不会发生冲突,所以事务开始的时候,不会加锁。只有在完成事务提交的时候做个校验。所以同时使用场景也是相对应的。他的场景就是对数据修改频率较低的场景。

第三:乐观锁的实现方式?

乐观锁的上面也说了他只是一种思想,msyql中的锁实现都是悲观锁。所以乐观锁的实现方式可以说是大家总结出的一种对于悲观锁弊端的优化方式-verson number

就是采用版本号的方式进行校验

具体:比如订单order表,我想要对他实现乐观锁。我就需要在订单表中添加一个字段叫verson或者其他也行,只要能表示版本号即可。每次提交就会校验版本号是否一致,并且将版本号+1.

第四:悲观锁的实现方式

悲观锁也是一种思想,与乐观锁不同的是他的事务一开始就会加了锁,而乐观锁实际上是没有锁的概念,只有版本号。在mysql中的锁都可以算所悲观锁。从锁的力度上来讲就是表级锁和行级锁

但是,不管是表级锁还是行级锁,他们的具体实现方式上分为共享锁和排他锁。也很好理解,共享锁主要就是读多写少的情况,排他锁就是读少写多的情况。

4.1 表级锁

先说一下表级锁吧,首先提示一下:表级锁慎用!!!顾名思义:就是将整个表给锁住了。这样的安全性极高,但是效率极低

4.1.1 表锁的共享锁实现方式

共享锁,实际就是针对于读取数据的情况,因为有些场景是需要高频次的读取某个表的数据并进行一些业务处理,为了防止别人修改数据,所以引入了共享锁。但是既然是锁,就会导致效率低下,所以共享锁的实现就是事务A读取order表的时候,把order表进行锁表,这时候别人都无法修改表中的任何数据。但是为了优化效率,可以允许别的事务也进行读取。

(一句话:只要一个事务给表加了共享锁,其他事务可以正常读取,但是无法修改)

4.1.2 表锁的排他锁实现方式

排他锁相对于共享锁就比较霸道了,也就是事务A对order表开启了排他锁,这时候,其他事务既不能读取表中的数据也不能修改表中的数据。

4.2 行级锁?

行级锁其实在平时的工作中倒是会有使用的情况,但是也不是很多,对于金融等行业可能会多一些。行级锁也是分为共享锁和排他锁,只不过区别是在于表级锁是针对的整个table,而行级锁是针对的某一行数据。所以就不画图了,只展示下具体的实现方式。

总的就是我对这一行数据加锁,表中其他数据可以正常操作。

4.2.1 行锁的共享锁实现方式

同理,对于id=1的这条数据加了共享锁,其他事务可以读取,但是提交之前不可修改。

-- 获取行级共享锁
START TRANSACTION;
SELECT * FROM your_table WHERE your_condition LOCK IN SHARE MODE;
-- 进行一些操作...
COMMIT;

这是针对于纯sql的形式,如果结合SpringBoot中的@Transactional注解后,你的sql就只需要写

SELECT * FROM your_table WHERE your_condition LOCK IN SHARE MODE;
-- 进行一些操作...

START 和 Commit框架会自动帮你处理。

4.2.2 行锁的排他锁实现方式

同理,事务A开启了排他锁,他在提交之前,其他事务既不能读取也不能修改这条数据。

-- 获取行级排它锁
START TRANSACTION;
SELECT * FROM your_table WHERE your_condition FOR UPDATE;
-- 进行一些操作...
COMMIT;

当然,如果结合SpringBoot中的@Transactional注解后,你的sql就只需要写

SELECT * FROM your_table WHERE your_condition FOR UPDATE;???????
-- 进行一些操作...

当然这些是平时项目中最常遇到的锁,还有一些比如:页级锁、间隙锁、自旋锁等等,不怎么常见,甚至不能显式的用SQL表达,后面会单独开篇文章记录其他几种锁,平时的面试如果能回答上来上述的也基本可以了。

结束!

文章来源:https://blog.csdn.net/qq_36178165/article/details/135403018
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。