高频|mysql事务隔离级别和锁的机制可以这么答

Bigsai Bigsai     2022-12-18     135

关键词:

  • 案例背景

  • MySQL 隔离级别

  • 案例分析

  • 案例解答

  • 死锁产生的四个必要条件:

案例背景

MySQL 的事务隔离级别(Isolation Level),是指:当多个线程操作数据库时,数据库要负责隔离操作,来保证各个线程在获取数据时的准确性。它分为四个不同的层次,按隔离水平高低排序,读未提交 < 读已提交 < 可重复度 < 串行化。

MySQL 隔离级别

  • 读未提交(Read uncommitted):隔离级别最低、隔离度最弱,脏读、不可重复读、幻读三种现象都可能发生。所以它基本是理论上的存在,实际项目中没有人用,但性能最高。

  • 读已提交(Read committed):它保证了事务不出现中间状态的数据,所有数据都是已提交且更新的,解决了脏读的问题。但读已提交级别依旧很低,它允许事务间可并发修改数据,所以不保证再次读取时能得到同样的数据,也就是还会存在不可重复读、幻读的可能。

  • 可重复读(Repeatable reads):MySQL InnoDB 引擎的默认隔离级别,保证同一个事务中多次读取数据的一致性,解决脏读和不可重复读,但仍然存在幻读的可能。

  • 可串行化(Serializable):选择“可串行化”意味着读取数据时,需要获取共享读锁;更新数据时,需要获取排他写锁;如果 SQL 使用 WHERE 语句,还会获取区间锁。换句话说,事务 A 操作数据库时,事务 B 只能排队等待,因此性能也最低。

至于数据库锁,分为悲观锁和乐观锁,“悲观锁”认为数据出现冲突的可能性很大,“乐观锁”认为数据出现冲突的可能性不大。那悲观锁和乐观锁在基于 MySQL 数据库的应用开发中,是如何实现的呢?

  • 悲观锁一般利用 SELECT … FOR UPDATE 类似的语句,对数据加锁,避免其他事务意外修改数据。

  • 乐观锁利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时间戳或者版本号,实现版本判断。

案例分析

如果面试官想深挖候选人对数据库内部机制的掌握程度,切入点一般是 MySQL 的事务和锁机制。接下来,我就从初中级研发工程师的角度出发,从概念到实践,带你掌握“MySQL 事务和锁机制”的高频考点:

举例说明什么是脏读、不可重复度和幻读(三者虽然基础,但很多同学容易弄混)?

MySQL 是怎么解决脏读、不可重复读,和幻读问题的?

你怎么理解死锁?

……

案例解答

怎么理解脏读、不可重复读和幻读?

脏读:读到了未提交事务的数据。

事务并发时的“脏读”现象

假设有 A 和 B 两个事务,在并发情况下,事务 A 先开始读取商品数据表中的数据,然后再执行更新操作,如果此时事务 A 还没有提交更新操作,但恰好事务 B 开始,然后也需要读取商品数据,此时事务 B 查询得到的是刚才事务 A 更新后的数据。

如果接下来事务 A 触发了回滚,那么事务 B 刚才读到的数据就是过时的数据,这种现象就是脏读。

“脏读”面试关注点:

  1. 脏读对应的隔离级别是“读未提交”,只有该隔离级别才会出现脏读。

  2. 脏读的解决办法是升级事务隔离级别,比如“读已提交”。

不可重复读: 事务 A 先读取一条数据,然后执行逻辑的过程中,事务 B 更新了这条数据,事务 A 再读取时,发现数据不匹配,这个现象就是“不可重复读”。

事务并发时的“不可重复读”现象

“不可重复读”面试关注点:

简单理解是两次读取的数据中间被修改,对应的隔离级别是“读未提交”或“读已提交”。

不可重复读的解决办法就是升级事务隔离级别,比如“可重复度”。

幻读: 在一个事务内,同一条查询语句在不同时间段执行,得到不同的结果集。

事务并发时的“幻读”现象

事务 A 读了一次商品表,得到最后的 ID 是 3,事务 B 也同样读了一次,得到最后 ID 也是 3。接下来事务 A 先插入了一行,然后读了一下最新的 ID 是 4,刚好是前面 ID 3 加上 1,然后事务 B 也插入了一行,接着读了一下最新的 ID 发现是 5,而不是 3 加 1。

这时,你发现在使用 ID 做判断或做关键数据时,就会出现问题,这种现象就像是让事务 B 产生了幻觉一样,读取到了一个意想不到的数据,所以叫幻读。当然,不仅仅是新增,删除、修改数据也会发生类似的情况。

“幻读”面试关注点:

要想解决幻读不能升级事务隔离级别到“可串行化”,那样数据库也失去了并发处理能力。

行锁解决不了幻读,因为即使锁住所有记录,还是阻止不了插入新数据。

解决幻读的办法是锁住记录之间的“间隙”,为此 MySQL InnoDB 引入了新的锁,叫间隙锁(Gap Lock),所以在面试中,你也要掌握间隙锁,以及间隙锁与行锁结合的 next-key lock 锁。

怎么理解死锁

除了事务隔离级别,很多同学在面试时,经常会被面试官直奔主题地问:“谈谈你对死锁的理解”。要回答这样开放的问题,你就要在脑海中梳理出系统化的回答思路:死锁是如何产生的,如何避免死锁。

死锁一般发生在多线程(两个或两个以上)执行的过程中。因为争夺资源造成线程之间相互等待,这种情况就产生了死锁。我在 06 讲也提到了死锁,但是并没有讲它产生的原因以及怎么避免,所以接下来我们就来了解这部分内容。

线程死锁

比如你有资源 1 和 2,以及线程 A 和 B,当线程 A 在已经获取到资源 1 的情况下,期望获取线程 B 持有的资源 2。与此同时,线程 B 在已经获取到资源 2 的情况下,期望获取现场 A 持有的资源 1。

那么线程 A 和线程 B 就处理了相互等待的死锁状态,在没有外力干预的情况下,线程 A 和线程 B 就会一直处于相互等待的状态,从而不能处理其他的请求。

死锁产生的四个必要条件:

互斥:多个线程不能同时使用一个资源。比如线程 A 已经持有的资源,不能再同时被线程 B 持有。如果线程 B 请求获取线程 A 已经占有的资源,那线程 B 只能等待这个资源被线程 A 释放。

持有并等待:当线程 A 已经持有了资源 1,又提出申请资源 2,但是资源 2 已经被线程 C 占用,所以线程 A 就会处于等待状态,但它在等待资源 2 的同时并不会释放自己已经获取的资源 1。

不可剥夺:线程 A 获取到资源 1 之后,在自己使用完之前不能被其他线程(比如线程 B)抢占使用。如果线程 B 也想使用资源 1,只能在线程 A 使用完后,主动释放后再获取。

循环等待:发生死锁时,必然会存在一个线程,也就是资源的环形链。比如线程 A 已经获取了资源 1,但同时又请求获取资源 2。线程 B 已经获取了资源 2,但同时又请求获取资源 1,这就会形成一个线程和资源请求等待的环形图。

死锁只有同时满足互斥、持有并等待、不可剥夺、循环等待时才会发生。并发场景下一旦死锁,一般没有特别好的方法,很多时候只能重启应用。因此,最好是规避死锁,那么具体怎么做呢?答案是:至少破坏其中一个条件(互斥必须满足,你可以从其他三个条件出发)。

  • 持有并等待:我们可以一次性申请所有的资源,这样就不存在等待了。

  • 不可剥夺:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源,这样不可剥夺这个条件就破坏掉了。

  • 循环等待:可以靠按序申请资源来预防,也就是所谓的资源有序分配原则,让资源的申请和使用有线性顺序,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样的线性化操作就自然就不存在循环了。

往期推荐

如何优雅地回答面试官关于MySQL索引的拷问

面试必问:MVCC机制了解吗

聊聊我是如何拿到这么多大厂offer

写好简历,合理准备,三面拿下腾讯offer

mysql的隔离级别和锁的关系

  MySql的隔离级别和锁的关系 一、事务的4个基本特征 Atomic(原子性): 事务中包括的操作被看做一个逻辑单元。这个逻辑单元中的操作要 么所有成功。要么所有失败。 Consistency(一致性): 仅仅... 查看详情

mysql数据库事务的隔离级别和锁的实现原理分析

mysql数据库的事务隔离级别相信很多同学都知道.大家有没有想过它是如何实现的呢?带着这些问题我翻阅了相关数据库的书籍和资料,把我的理解写下来.一:事务隔离级别mysql数据库的隔离界别如下:1,READUNCOMMITTED(未提交读)事务... 查看详情

innodb中的事务隔离级别和锁的关系

http://blog.csdn.net/zcgsdu/article/details/44965753前言:我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁... 查看详情

深入了解mysql的隔离级别和锁机制

简述:我们的MySQL一般会并发的执行多个事务,多个事务可能会并发的对同一条或者同一批数据进行crud操作;可能就会导致我们平常所说的脏读、不可重复读、幻读这些问题.这些问题的本质都是MySQL多事务并发问题,为了解决多事务... 查看详情

事务和锁机制是啥关系?开启事务就自动加锁了吗?菜鸟,谢谢了。

1、事务与锁是不同的。事务具有ACID(原子性、一致性、隔离性和持久性),锁是用于解决隔离性的一种机制。2、事务的隔离级别通过锁的机制来实现。另外锁有不同的粒度,同时事务也是有不同的隔离级别的。3、开启事务就... 查看详情

mysql事务隔离性与相关锁的总结(代码片段)

事务隔离级别隔离级别脏读不可重复读幻读读未提交可以出现可以出现可以出现读提交不允许出现可以出现可以出现可重复读不允许出现不允许出现可以出现序列化不允许出现不允许出现不允许出现注意点上述隔离级别都是这么... 查看详情

程序员面试宝典之mysql数据库innodb引擎的4个隔离级别

...别难度:三星面试频率:五星这道题真的是一道数据库的高频题,数据库题除了索引的原理之外就是这道题的面试频率最高。1.Readuncommitted(读未提交):,最低的隔离级别,可以一个事务读到其他事务没有提交的数据,也称脏... 查看详情

mysql锁的分类和加锁机制(代码片段)

...先我们必须要明白加锁的是为了解决什么问题。我们知道事务具有个隔离性的特性,而隔离性的实现主要就是通过锁以及MVCC机制实现的(关于MVCC机制以及隔离级别的实现可查看文章:MySQL事务详解与隔离级别的实现&#... 查看详情

mysql事务和隔离级别

MySQL事务和隔离级别连接管理器: 接受请求 创建线程 认证用户 建立安全连接 并发控制: 最简单机制是使用锁 多版本并发控制:MVCC(使用其他机制)锁: 读锁:共享锁 写锁:独占锁 加锁: LOCKTABLEStb_name{READ|WRITE}; 解锁: UNL... 查看详情

数据库事务中的隔离级别和锁+springtransactional注解

数据库事务中的隔离级别和锁数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性、安全性也是我们需要研究的问题。ACID首先总结一下数据库事务正确执行的四个要素(ACID):原子性(Atomicity):即事务是... 查看详情

mysql事务篇:acid原则事务隔离级别及事务机制原理剖析

引言众所周知,​​MySQL​​数据库的核心功能就是存储数据,通常是整个业务系统中最重要的一层,可谓是整个系统的“大本营”,因此只要​​MySQL​​存在些许隐患问题,对于整个系统而言都是致命的。那此刻不妨思考一... 查看详情

图解mvcc机制

...脏写、脏读、不可重复读、幻读,四种问题。MySQL默认的事务隔离级别是RR(可重复读),而且MySQL的RR级别是可以避免幻读发生。也就是说,MySQL里执行的事务,默认情况下不会发生脏写、脏读、不可重复读和幻读的问题。如何... 查看详情

mysql-锁

InnoDB在不同隔离级别下的一致性读及锁的差异前面讲过,锁和多版本数据是InnoDB实现一致性读和ISO/ANSISQL92隔离级别的手段,因此,在不同的隔离级别下,InnoDB处理SQL时采用的一致性读策略和需要的锁是不同的。同时,数据恢复... 查看详情

事务隔离级别

两个锁:排他锁被加锁的对象只能被持有锁的事务读取和修改,其他事务无法在该对象上加其他锁,也不能读取和修改该对象共享锁被加锁的对象可以被持锁事务读取,但是不能被修改,其他事务也可以在上面再加共享锁。 ... 查看详情

mysql之事务和锁机制(代码片段)

文章目录一、事务1.1事务特征1.2隔离级别1.3开启事务二、锁机制2.1读锁、写锁2.2全局锁、表锁、行锁2.3记录锁、间隙锁、临键锁提示:以下是本篇文章正文内容,MySQL系列学习将会持续更新一、事务在数据库里面,我... 查看详情

node.jsmysql事务和锁的写法

一、安装相关包npminstallaccess-dbnpminstalldotenv然后在项目入口文件(如app.js)的最前面引入require('dotenv').config()新建.env文件,并添加mysql配置。MYSQL_HOST=localhost//必填MYSQL_USER=rootMYSQL_PASSWORD=123456MYSQL_PORT=3306MYSQL_DATAB 查看详情

事务隔离级别与表上的锁的关系

】事务隔离级别与表上的锁的关系【英文标题】:Transactionisolationlevelsrelationwithlocksontable【发布时间】:2013-04-1606:07:09【问题描述】:我已经阅读了大约4个隔离级别:IsolationLevelDirtyReadNonrepeatableReadPhantomReadREADUNCOMMITTEDPermittedPermit... 查看详情

第36讲谈谈mysql支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景

...践中深入学习。今天我要问你的问题是,谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场 查看详情